﻿namespace System.NETool;

public static class MathEx
{
    /// <summary>
    /// 判断是否是偶数
    /// </summary>
    /// <param name="this">整数值</param>
    /// <returns>如果是偶数返回 true，否则返回 false</returns>
    public static bool IsEven(this int @this)
    {
        return @this % 2 == 0;
    }

    /// <summary>
    /// 判断是否是奇数
    /// </summary>
    /// <param name="this">整数值</param>
    /// <returns>如果是奇数返回 true，否则返回 false</returns>
    public static bool IsOdd(this int @this)
    {
        return @this % 2 != 0;
    }

    /// <summary>
    /// 判断是否是偶数
    /// </summary>
    /// <param name="this">长整数值</param>
    /// <returns>如果是偶数返回 true，否则返回 false</returns>
    public static bool IsEven(this long @this)
    {
        return @this % 2 == 0;
    }

    /// <summary>
    /// 判断是否是奇数
    /// </summary>
    /// <param name="this">长整数值</param>
    /// <returns>如果是奇数返回 true，否则返回 false</returns>
    public static bool IsOdd(this long @this)
    {
        return @this % 2 != 0;
    }

    /// <summary>
    /// 对浮点数进行四舍五入取整
    /// </summary>
    /// <param name="this">浮点数值</param>
    /// <returns>取整后的整数值</returns>
    public static int RoundEx(this float @this)
    {
        return (int)(@this + 0.5f);
    }

    /// <summary>
    /// 对双精度浮点数进行四舍五入取整
    /// </summary>
    /// <param name="this">双精度浮点数值</param>
    /// <returns>取整后的整数值</returns>
    public static int RoundEx(this double @this)
    {
        return (int)(@this + 0.5);
    }

    /// <summary>
    /// 判断两个浮点数是否相等
    /// </summary>
    /// <param name="this">第一个浮点数</param>
    /// <param name="value">第二个浮点数</param>
    /// <param name="eps">允许的误差范围</param>
    /// <returns>如果相等返回 true，否则返回 false</returns>
    public static bool EqualsFloat(this float @this, float value, float eps = 0.00000001f)
    {
        return Math.Abs(@this - value) < eps;
    }

    /// <summary>
    /// 判断两个浮点数是否不相等
    /// </summary>
    /// <param name="this">第一个浮点数</param>
    /// <param name="value">第二个浮点数</param>
    /// <param name="eps">允许的误差范围</param>
    /// <returns>如果不相等返回 true，否则返回 false</returns>
    public static bool NotEquals(this float @this, float value, float eps = 0.00000001f)
    {
        return Math.Abs(@this - value) >= eps;
    }

    /// <summary>
    /// 判断两个双精度浮点数是否相等
    /// </summary>
    /// <param name="this">第一个双精度浮点数</param>
    /// <param name="value">第二个双精度浮点数</param>
    /// <param name="eps">允许的误差范围</param>
    /// <returns>如果相等返回 true，否则返回 false</returns>
    public static bool EqualsDouble(this double @this, double value, double eps = 0.00000001)
    {
        return Math.Abs(@this - value) < eps;
    }

    /// <summary>
    /// 判断两个双精度浮点数是否不相等
    /// </summary>
    /// <param name="this">第一个双精度浮点数</param>
    /// <param name="value">第二个双精度浮点数</param>
    /// <param name="eps">允许的误差范围</param>
    /// <returns>如果不相等返回 true，否则返回 false</returns>
    public static bool NotEquals(this double @this, double value, double eps = 0.00000001)
    {
        return Math.Abs(@this - value) >= eps;
    }

    /// <summary>
    /// 得到最接近且大于等于指定数字的二的N次方数
    /// </summary>
    /// <param name="value">指定的整数值</param>
    /// <returns>大于等于指定数字的二的N次方数</returns>
    public static int Get2PowNHigh(int value)
    {
        if (value < 1) return 1;
        --value; // 避免正好输入一个2的次方数
        value |= value >> 1;
        value |= value >> 2;
        value |= value >> 4;
        value |= value >> 8;
        value |= value >> 16;
        return ++value;
    }

    /// <summary>
    /// 得到最接近且小于等于指定数字的二的N次方数
    /// </summary>
    /// <param name="value">指定的整数值</param>
    /// <returns>小于等于指定数字的二的N次方数</returns>
    public static int Get2PowNLow(int value)
    {
        return Get2PowNHigh(value) >> 1;
    }

    /// <summary>
    /// 整数除法取整
    /// </summary>
    /// <param name="this">被除数</param>
    /// <param name="divParam">除数</param>
    /// <returns>除法取整结果</returns>
    public static int Div(this int @this, int divParam)
    {
        return @this / divParam;
    }

    /// <summary>
    /// 整数除法取余
    /// </summary>
    /// <param name="this">被除数</param>
    /// <param name="divParam">除数</param>
    /// <returns>除法取余结果</returns>
    public static int Mod(this int @this, int divParam)
    {
        return @this % divParam;
    }

    /// <summary>
    /// 角度转弧度
    /// </summary>
    /// <param name="this">角度值</param>
    /// <returns>弧度值</returns>
    public static double Rad(this double @this)
    {
        return @this * Math.PI / 180.0;
    }

    /// <summary>
    /// 弧度转角度
    /// </summary>
    /// <param name="this">弧度值</param>
    /// <returns>角度值</returns>
    public static double Deg(this double @this)
    {
        return @this * 180.0 / Math.PI;
    }

    /// <summary>
    /// 角度转弧度
    /// </summary>
    /// <param name="this">角度值</param>
    /// <returns>弧度值</returns>
    public static double Rad(this float @this)
    {
        return @this * Math.PI / 180.0;
    }

    /// <summary>
    /// 弧度转角度
    /// </summary>
    /// <param name="this">弧度值</param>
    /// <returns>角度值</returns>
    public static double Deg(this float @this)
    {
        return @this * 180.0 / Math.PI;
    }
}
